package pres.seanlang.utility;

/**
 *  事件锁工具
 *
 * @author SeanLang
 */
public final class LockUtils {
    static public final int FAILURE = 0x00;
    static public final int SUCCESS = 0x01;

    private Object object;

    protected LockUtils(Object obj) {
        //throw new UnsupportedOperationException("Do not need instantiate!");
        this.object = obj;
    }

    /**
     *  创建指定obj的锁对象
     * @param lockObj
     * @return
     */
    static public LockUtils create(Object lockObj) {
        return new LockUtils(lockObj);
    }

    /**
     *  创建默认锁对象
     * @return
     */
    static public LockUtils create() {
        return create(new Object());
    }

    /**
     *  解锁
     */
    public void unlock() {
        synchronized (object) {
            object.notifyAll();
        }
    }

    /**
     *  锁定
     * @return  {@link #SUCCESS}成功, {@link #FAILURE}失败
     */
    public int lock() {
        synchronized (object) {
            try {
                object.wait();
                return SUCCESS;
            } catch (InterruptedException e) {
                //throw new RuntimeException(e);
                System.err.println("EventLock lock error. " + e.getLocalizedMessage());
            }
        }

        return FAILURE;
    }

    /**
     * 锁定
     * @param waitMs    等待时间
     * @return  {@link #SUCCESS}成功, {@link #FAILURE}失败
     */
    public int lock(long waitMs) {
        synchronized (object) {
            try {
                long startTime = System.currentTimeMillis();
                object.wait(waitMs);
                long delay = System.currentTimeMillis() - startTime;
                if(delay > waitMs) {
                    System.err.println("EventLock lock wait timeout.");
                    return FAILURE;
                } else {
                    return SUCCESS;
                }
            } catch (InterruptedException e) {
                //throw new RuntimeException(e);
                System.err.println("EventLock lock error. " + e.getLocalizedMessage());
            }
        }

        return FAILURE;
    }
}
